/*************************************************
Author: tony
Date: 11/26/2012
Description:
Notes:
*************************************************/

#ifndef __CDrugConfig_h__
#define __CDrugConfig_h__

#include "commerrno.h"
#include "commclass.h"
#include "CTSizeString.h"
#include "CTHashObjectMgr.h"

class CDrugConfigKey
{
public:
    CDrugConfigKey()
    {
        _ucDrugLevel = 0;
        _ucDrugAttr = 0;
    }

    unsigned char _ucDrugLevel;
    unsigned char _ucDrugAttr;

    bool operator==(const CDrugConfigKey & stKey) const
    {
        return (_ucDrugLevel == stKey._ucDrugLevel && _ucDrugAttr == stKey._ucDrugAttr);
    }
};

class CDrugConfigData
{
public:
	CDrugConfigData()
    {
        _stKey._ucDrugAttr = 0;
        _stKey._ucDrugLevel = 0;
        _usDrugConfigID = 0;
        _usScrollId = 0;
	}

	virtual ~CDrugConfigData()
    {
	}

public:
    CDrugConfigKey _stKey;
	unsigned short _usDrugConfigID;
    unsigned short _usScrollId;          //制造卷轴ID
};

class CDrugOperKey
{
public:
    CDrugOperKey()
    {
        _ucLevel = 0;
        _ucStage = 0;
    }

    unsigned char _ucLevel;
    unsigned char _ucStage;

    bool operator==(const CDrugOperKey& stKey) const
    {
        return (_ucLevel == stKey._ucLevel && _ucStage == stKey._ucStage);
    }
};

class CSyntheDrugConfig
{
public:
    CSyntheDrugConfig()
    {
        _stSyntheKey._ucLevel = 0;
        _stSyntheKey._ucStage = 0;
        _ucAttrAddition = 0;
        _ucDrugCapacity = 0;
    }

    virtual ~CSyntheDrugConfig()
    {
    }

public:
    CDrugOperKey _stSyntheKey;
    unsigned char _ucDrugCapacity;
    unsigned char _ucAttrAddition;
};

class CPurifyDrugConfig
{
public:
    CPurifyDrugConfig()
    {
        _stPurifyKey._ucLevel = 0;
        _stPurifyKey._ucStage = 0;
        _ucAttrAddition = 0;

        _usPotionId = 0;
        _usNeedPotionCnt = 0;

        _uiNeedSilver = 0;
        _usNeedGold = 0;
    }

public:
    CDrugOperKey  _stPurifyKey;

    unsigned char _ucAttrAddition;  //这个阶段提纯满时,累计获得的属性值
    unsigned short _usPotionId;     //提纯剂配置ID
    unsigned short _usNeedPotionCnt;

    unsigned int   _uiNeedSilver;  //合成所需银币
    unsigned short _usNeedGold;    //立即合成所需金币
};


class CDrugInheritCfg
{
public:
    unsigned char _ucLevel;
    int _iSynGold;
    int _iSynSilver;
    int _iPuriGold;
    int _iPuriSilver;
};

class CDrugConfig
{
public:
    typedef CTLib::CTHashObjectMgr<CDrugOperKey, CSyntheDrugConfig>    T_SYNTHE_DRUG_CONFIG_HASH;
    typedef CTLib::CTHashObjectMgr<CDrugOperKey, CPurifyDrugConfig>  T_PURIFY_DRUG_CONFIG_HASH;

	CDrugConfig()
    {

	}

	virtual ~CDrugConfig()
    {
	}

    static int CountSize()
    {
        return T_SYNTHE_DRUG_CONFIG_HASH::CountSize(MAX_DRUG_SYNTHE_CONFIG_COUNT)
			 + T_PURIFY_DRUG_CONFIG_HASH::CountSize(MAX_DRUG_PURIFY_CONFIG_COUNT);
    }

    int Init(const char* sBuff)
	{
        int iRet = 0;
        int iOffset = 0;

        iRet = _stSyntheDrugConfigHash.Init(sBuff + iOffset, MAX_DRUG_SYNTHE_CONFIG_COUNT);
        CHECK_RETURN(iRet);
        iOffset += T_SYNTHE_DRUG_CONFIG_HASH::CountSize(MAX_DRUG_SYNTHE_CONFIG_COUNT);

        iRet = _stPurifyDrugConfigHash.Init(sBuff + iOffset, MAX_DRUG_PURIFY_CONFIG_COUNT);
        CHECK_RETURN(iRet);
        iOffset += T_PURIFY_DRUG_CONFIG_HASH::CountSize(MAX_DRUG_PURIFY_CONFIG_COUNT);

		return 0;
	}

    bool IsValidDrug (unsigned short usDrugId)
    {
        if (usDrugId > MAX_DRUG_CONFIG_ID || usDrugId == 0)
        {
            return false;
        }

        return true;
    }

    int AddDrugConfigData(CDrugConfigData & stConfigData)
    {
        if (!IsValidDrug(stConfigData._usDrugConfigID))
        {
            return ERROR_DRUG_WRONG_CONFIG;
        }

        if (0 == stConfigData._stKey._ucDrugLevel
            || stConfigData._stKey._ucDrugLevel > MAX_DRUG_LEVEL)
        {
            return ERROR_DRUG_WRONG_CONFIG;
        }

        _astDrugConfig[stConfigData._usDrugConfigID] = stConfigData;
        return 0;
    }

    CDrugConfigData & GetDrugConfigData(unsigned short usDrugId)
    {
        return _astDrugConfig[usDrugId];
    }

    int AddSyntheDrugCfg(CSyntheDrugConfig & stConfigData)
    {
        int iIndex = _stSyntheDrugConfigHash.HashAlloc(stConfigData._stSyntheKey);
        if (iIndex < 0)
        {
            CT_ERROR(("add make drug config full"));
            return RET_SYSTEM_FAIL;
        }

        _stSyntheDrugConfigHash[iIndex] = stConfigData;
        return 0;
    }

    int GetSyntheDrugCfg(CDrugOperKey &stKey, CSyntheDrugConfig & stConfigData)
    {
        if (0 == stKey._ucStage)
        {
            stConfigData._stSyntheKey._ucLevel = stKey._ucLevel;
            stConfigData._stSyntheKey._ucStage = 0;
            stConfigData._ucAttrAddition = 0;
            stConfigData._ucDrugCapacity = 0;
            return 0;
        }

        int iIndex = _stSyntheDrugConfigHash.HashFind(stKey);
        if (iIndex < 0)
        {
            return ERROR_DRUG_NO_CONFIG;
        }

        stConfigData = _stSyntheDrugConfigHash[iIndex];

        return 0;
    }

    short GetSynFloorCapacity(short shCapacity)
    {
        if (shCapacity < 30)
        {
            return 0;
        }
        else
        {
            return 30;
        }

        return 0;
    }

    int GetSyntheCfg (unsigned short usDrugId, short shCapacity, CSyntheDrugConfig & stConfigData)
    {
        if (shCapacity <= 0)
        {
            return 0;
        }

        CDrugConfigData & stConfig = GetDrugConfigData(usDrugId);
        shCapacity = shCapacity > MAX_DRUG_CAPACITY ? MAX_DRUG_CAPACITY : shCapacity;

        CDrugOperKey stKey;
        stKey._ucLevel = stConfig._stKey._ucDrugLevel;

        int i = 0;
        for (; i < MAX_DRUG_CONFIG_ID; i++)
        {
            stKey._ucStage = i;
            int iRet = GetSyntheDrugCfg(stKey, stConfigData);
            if (RET_OK != iRet)
            {
                return ERROR_DRUG_WRONG_CONFIG;
            }

            if (stConfigData._ucDrugCapacity == shCapacity)
            {
                return 0;
            }
        }

        return ERROR_DRUG_WRONG_CONFIG;
    }

    // 返回值等于0, 炼药为初始阶段. 大于0, 表示有效的炼药阶段
    int GetSyntheAttr (unsigned short usDrugId, short shCapacity, int & iAttr)
    {
        iAttr = 0;

        CSyntheDrugConfig stConfigData;
        int iRet = GetSyntheCfg (usDrugId, shCapacity, stConfigData);
        CHECK_RETURN(iRet);

        iAttr = stConfigData._ucAttrAddition;
        return 0;
    }

    int AddPurifyDrugCfg(CPurifyDrugConfig & stConfigData)
    {
        int iIndex = _stPurifyDrugConfigHash.HashAlloc(stConfigData._stPurifyKey);
        if (iIndex < 0)
        {
            CT_ERROR(("add purify drug config full"));
            return RET_SYSTEM_FAIL;
        }

        _stPurifyDrugConfigHash[iIndex] = stConfigData;

        return 0;
    }

    int GetPurifyDrugCfg (CDrugOperKey &stKey, CPurifyDrugConfig & stConfigData)
    {
        int iIndex = _stPurifyDrugConfigHash.HashFind(stKey);
        if (iIndex < 0)
        {
            return ERROR_DRUG_NO_CONFIG;
        }

        stConfigData = _stPurifyDrugConfigHash[iIndex];

        return 0;
    }

    int AddInheritCfg (CDrugInheritCfg & stConfigData)
    {
        if (0 == stConfigData._ucLevel
            || stConfigData._ucLevel > MAX_DRUG_LEVEL)
        {
            return ERROR_DRUG_WRONG_CONFIG;
        }

        _astInheritCfg[stConfigData._ucLevel - 1] = stConfigData;
        return 0;
    }

    CDrugInheritCfg & GetInheritCfg (unsigned char ucLevel)
    {
        return _astInheritCfg[ucLevel-1];
    }

    int  GetPurifyAttr(unsigned char ucLevel, short shCapacity, int & iAttr)
    {
        iAttr = 0;
        if (shCapacity < MAX_DRUG_CAPACITY + MAX_PURIFY_PER_LEVEL)
        {
            return 0;
        }

        CDrugOperKey stKey;
        stKey._ucLevel = ucLevel;
        stKey._ucStage = (shCapacity - MAX_DRUG_CAPACITY) / MAX_PURIFY_PER_LEVEL - 1;
        int iIndex = _stPurifyDrugConfigHash.HashFind(stKey);
        if (iIndex < 0)
        {
            CT_ERROR(("%d, %d", stKey._ucLevel, stKey._ucStage));
            return ERROR_DRUG_NO_CONFIG;
        }

        iAttr = _stPurifyDrugConfigHash[iIndex]._ucAttrAddition;
        return 0;
    }


public:
    CTArray<CDrugConfigData, MAX_DRUG_CONFIG_COUNT>   _astDrugConfig;
    CTArray<CDrugInheritCfg, MAX_DRUG_LEVEL>  _astInheritCfg;
    T_SYNTHE_DRUG_CONFIG_HASH  _stSyntheDrugConfigHash;
    T_PURIFY_DRUG_CONFIG_HASH _stPurifyDrugConfigHash;

};

namespace __gnu_cxx
{
    template<> struct hash<CDrugOperKey>
    {
        size_t operator()(const CDrugOperKey & x) const
        {
            return (x._ucStage * MAX_DRUG_LEVEL + x._ucLevel);
        }
    };
}


#endif // __CDrugConfig_h__

